home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Utilities / Converters / Convert_TEXT / Source / shared.subproj / NeXTToMacText.m < prev    next >
Text File  |  1995-06-12  |  18KB  |  468 lines

  1. /***********************************************************************\
  2. Common class for converting NeXT to Mac text in all Convert programs
  3. Copyright (C) 1993 David John Burrowes
  4.  
  5. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 1, or (at your option) any later version.
  6.  
  7. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
  8.  
  9. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  10.  
  11. The author, David John Burrowes, can be reached at:
  12.     davidjohn@kira.net.netcom.com
  13.     David John Burrowes
  14.     1926 Ivy #10
  15.     San Mateo, CA 94403-1367
  16. \***********************************************************************/
  17.  
  18. /*====================================================================
  19. This is the implementation file for the NeXTToMacText class.  Full documentation for this class can be found in the NeXTToMacText.rtf file.  I will not duplicate all that fine information here.
  20.  
  21. NOTE: You may find that text doesn't line up properly unless you use the New Century Schoolbook Roman typeface, since this was created with it.
  22.  
  23. INFORMATION:
  24.     This is $Revision: 1.2 $ of this file
  25.     It was last modifiFed by $Author: death $ on $Date: 93/04/04 23:44:44 $
  26.      $Log:    NeXTToMacText.m,v $
  27. Revision 1.2  93/04/04  23:44:44  death
  28. Sun Apr  4 23:44:44 PDT 1993
  29.  
  30. Revision 1.1  93/01/10  15:08:29  death
  31. Sun Jan 10 15:08:29 PST 1993
  32.  
  33. ====================================================================*/
  34.  
  35.  
  36. #import "NeXTToMacText.h"
  37. #import <memory.h>    // for memcpy
  38. #include <strings.h>
  39.  
  40.  
  41. @implementation NeXTToMacText
  42.  
  43.  
  44. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  45. //    Routine:        init:
  46. //    Parameters:    none
  47. //    Returns:        self
  48. //    Stores:        none
  49. //    Description:
  50. //        This initalizes the object by filling in the convert array that it uses to
  51. //        dictate most of its character conversions.
  52. //    Bugs:
  53. //        Note that we store a null to indicate any characters that can't be
  54. //        converted directly.  Because of this strategy, the null character must be dealt
  55. //        with in this object, though really it is part of the superclass' territory.
  56. //        other more complex implementations (keep a flag with each array entry
  57. //        to indicate if we can convert to it, or keep integers so one can store more than
  58. //        one of 256 values in an entry  might be used to reimplement this if needed.
  59. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60. - (Instance) init
  61. {
  62.     Integer    counter;
  63.     //
  64.     [super init];
  65.     
  66.     UseCurlyQuotes = NO;
  67.     //
  68.     //    Initialize conversion array with whatever our superclass likes to do.
  69.     //
  70.     for (counter = 0; counter < 256; counter++)
  71.         ConvertArray[counter] = [super     ConvertCharacter: (Character) counter];
  72.     //
  73.     //    We view the world as: we are just like whatever our superclass is, except
  74.     //    that we differ for characters 0,  NL, and anything above 128. =)  So,
  75.     //    modify the table to reflect all of this.  (note: indices are essencially mac
  76.     //    character codes, while values we are assigning are NeXT character codes).
  77.     //
  78.     ConvertArray[NEWLINE] = CARRIAGERETURN; // Convert line endings
  79.     //    0x8X
  80.     ConvertArray[0x80] = 0xCA;        // (nbspace)next
  81.     ConvertArray[0x81] = 0xCB;        // (Agrave)
  82.     ConvertArray[0x82] = 0xE7;        // (Aacute)
  83.     ConvertArray[0x83] = 0xE5;        // (Acircumflex)
  84.     ConvertArray[0x84] = 0xCC;        // (Atilde)
  85.     ConvertArray[0x85] = 0x80;        // (Adieresis)
  86.     ConvertArray[0x86] = 0x81;        // (Aring)
  87.     ConvertArray[0x87] = 0x82;        // (Ccedilla)
  88.     ConvertArray[0x88] = 0xE9;        // (Egrave)
  89.     ConvertArray[0x89] = 0x83;        // (Eacute)
  90.     ConvertArray[0x8A] = 0xE6;        // (Ecircumflex)
  91.     ConvertArray[0x8B] = 0xE8;        // (Edieresis)
  92.     ConvertArray[0x8C] = 0xED;        // (Igrave)
  93.     ConvertArray[0x8D] = 0xEA;        // (Iacute)
  94.     ConvertArray[0x8E] = 0xEB;        // (Icircumflex)
  95.     ConvertArray[0x8F] = 0xEC;        // (Idieresis)
  96.     //    0x9X
  97.     ConvertArray[0x90] = NullCharacter;    // (Eth)
  98.     ConvertArray[0x91] = 0x84;        // (Ntilde)
  99.     ConvertArray[0x92] = 0xF1;        // (Ograve)
  100.     ConvertArray[0x93] = 0xEE;        // (Oacute)
  101.     ConvertArray[0x94] = 0xEF;        // (Ocircumflex)
  102.     ConvertArray[0x95] = 0xCD;        // (Otilde)
  103.     ConvertArray[0x96] = 0x85;        // (Odieresis)
  104.     ConvertArray[0x97] = 0xF4;        // (Ugrave)
  105.     ConvertArray[0x98] = 0xF2;        // (Uacute)
  106.     ConvertArray[0x99] = 0xF3;        // (Ucircumflex)
  107.     ConvertArray[0x9A] = 0x86;        // (Udieresis)
  108.     ConvertArray[0x9B] = NullCharacter;    // (Yacute)
  109.     ConvertArray[0x9C] = NullCharacter;    // (Thorn)
  110.     ConvertArray[0x9D] = 0xB5;        // (mu)
  111.     ConvertArray[0x9E] = NullCharacter;            // (multiply)
  112.     ConvertArray[0x9F] = 0xD6;        // (divide)
  113.     //    0xAX
  114.     ConvertArray[0xA0] = 0xA9;        // (copyrightserif)
  115.     ConvertArray[0xA1] = 0xC1;        // (exclamdown)
  116.     ConvertArray[0xA2] = 0xA2;        // (cent)
  117.     ConvertArray[0xA3] = 0xA3;        // (sterling)
  118.     ConvertArray[0xA4] = 0xDA;        // (fraction)
  119.     ConvertArray[0xA5] = 0xB4;        // (yen)
  120.     ConvertArray[0xA6] = 0xC4;        // (florin)
  121.     ConvertArray[0xA7] = 0xA4;        // (section)
  122.     ConvertArray[0xA8] = 0xDB;        // (currency)
  123.     ConvertArray[0xA9] = 0x27;        // (quotesingle)
  124.     ConvertArray[0xAA] = 0xD2;        // (quotedblleft)
  125.     ConvertArray[0xAB] = 0xC7;        // (guillemotleft)
  126.     ConvertArray[0xAC] = 0xDC;        // (guilsinglleft)
  127.     ConvertArray[0xAD] = 0xDD;        // (guilsinglright)
  128.     ConvertArray[0xAE] = 0xDE;        // (fi)
  129.     ConvertArray[0xAF] = 0xDF;        // (fl)
  130.     //    0xBX
  131.     ConvertArray[0xB0] = 0xA8;        // (registerserif)
  132.     ConvertArray[0xB1] = 0xD0;        // (endash)
  133.     ConvertArray[0xB2] = 0xA0;        // (dagger)
  134.     ConvertArray[0xB3] = 0xE0;        // (daggerdbl)
  135.     ConvertArray[0xB4] = 0xE1;        // (periodcentered)
  136.     ConvertArray[0xB5] = NullCharacter;    // (brokenbar)
  137.     ConvertArray[0xB6] = 0xA6;        // (paragraph)
  138.     ConvertArray[0xB7] = 0xA5;        // (bullet)
  139.     ConvertArray[0xB8] = 0xE2;        // (quotesinglebase)
  140.     ConvertArray[0xB9] = 0xE3;        // (quotedblbase)
  141.     ConvertArray[0xBA] = 0xD3;        // (quotedblright)
  142.     ConvertArray[0xBB] = 0xC8;        // (guillemotright)
  143.     ConvertArray[0xBC] = 0xC9;        // (elipsis)
  144.     ConvertArray[0xBD] = 0xE4;        // (perthousand)
  145.     ConvertArray[0xBE] = 0xC2;        // (logicalnot)
  146.     ConvertArray[0xBF] = 0xC0;        // (questiondown)
  147.     //    0xCX
  148.     ConvertArray[0xC0] = NullCharacter;            // (onesuperior)
  149.     ConvertArray[0xC1] = 0x60;        // (grave)
  150.     ConvertArray[0xC2] = 0xAB;        // (acute)
  151.     ConvertArray[0xC3] = 0xF6;        // (circumflex)
  152.     ConvertArray[0xC4] = 0xF7;        // (tilde)
  153.     ConvertArray[0xC5] = 0xF8;        // (macron)
  154.     ConvertArray[0xC6] = 0xF9;        // (breve)
  155.     ConvertArray[0xC7] = 0xFA;        // (dotaccent)
  156.     ConvertArray[0xC8] = 0xAC;        // (dieresis)
  157.     ConvertArray[0xC9] = NullCharacter;    // (twosuperior)
  158.     ConvertArray[0xCA] = 0xFB;        // (ring)
  159.     ConvertArray[0xCB] = 0xFC;        // (cedilla)
  160.     ConvertArray[0xCC] = NullCharacter;    // (threesuperior)
  161.     ConvertArray[0xCD] = 0xFD;        // (hungarumlaut)
  162.     ConvertArray[0xCE] = 0xFE;        // (ogonek)
  163.     ConvertArray[0xCF] = 0xFF;        // (caron)
  164.     //    0xDX
  165.     ConvertArray[0xD0] = 0xD1;        // (emdash)
  166.     ConvertArray[0xD1] = 0xB1;        // (plusminus)
  167.     ConvertArray[0xD2] = NullCharacter;    // (onequarter)
  168.     ConvertArray[0xD3] = NullCharacter;    // (onehalf)
  169.     ConvertArray[0xD4] = NullCharacter;    // (threequarters)
  170.     ConvertArray[0xD5] = 0x88;        // (agrave)
  171.     ConvertArray[0xD6] = 0x87;        // (aacute)
  172.     ConvertArray[0xD7] = 0x89;        // (acircumflex)
  173.     ConvertArray[0xD8] = 0x8B;        // (atilde)
  174.     ConvertArray[0xD9] = 0x8A;        // (adieresis)
  175.     ConvertArray[0xDA] = 0x8C;        // (aring)
  176.     ConvertArray[0xDB] = 0x8D;        // (ccedilla)
  177.     ConvertArray[0xDC] = 0x8F;        // (egrave)
  178.     ConvertArray[0xDD] = 0x8E;        // (eacute)
  179.     ConvertArray[0xDE] = 0x90;        // (ecircumflex)
  180.     ConvertArray[0xDF] = 0x91;        // (dieresis)
  181.     //    0xE0
  182.     ConvertArray[0xE0] = 0x93;        // (igrave)
  183.     ConvertArray[0xE1] = 0xAE;        // (AE)
  184.     ConvertArray[0xE2] = 0x92;        // (iacute)
  185.     ConvertArray[0xE3] = 0xBB;        // (ordfeminine)
  186.     ConvertArray[0xE4] = 0x94;        // (icircumflex)
  187.     ConvertArray[0xE5] = 0x95;        // (idieresis)
  188.     ConvertArray[0xE6] = NullCharacter;    // (eth)
  189.     ConvertArray[0xE7] = 0x96;        // (ntilde)
  190.     ConvertArray[0xE8] = NullCharacter;    // (Lslash)
  191.     ConvertArray[0xE9] = 0xAF;        // (Oslash)
  192.     ConvertArray[0xEA] = 0xCE;        // (OE)
  193.     ConvertArray[0xEB] = 0xBC;        // (ordmasculine)
  194.     ConvertArray[0xEC] = 0x98;        // (ograve)
  195.     ConvertArray[0xED] = 0x97;        // (oacute)
  196.     ConvertArray[0xEE] = 0x99;        // (ocircumflex)
  197.     ConvertArray[0xEF] = 0x9B;        // (otilde)
  198.     //    0xF0
  199.     ConvertArray[0xF0] = 0x9A;        // (odieresis)
  200.     ConvertArray[0xF1] = 0xBE;        // (ae)
  201.     ConvertArray[0xF2] = 0x9D;        // (ugrave)
  202.     ConvertArray[0xF3] = 0x9C;        // (uacute)
  203.     ConvertArray[0xF4] = 0x9E;        // (ucircumflex)
  204.     ConvertArray[0xF5] = 0xF5;        // (dotlessi)
  205.     ConvertArray[0xF6] = 0x9F;        // (udieresis)
  206.     ConvertArray[0xF7] = NullCharacter;    // (yacute)
  207.     ConvertArray[0xF8] = NullCharacter;    // (lslash)
  208.     ConvertArray[0xF9] = 0xBF;        // (oslash)
  209.     ConvertArray[0xFA] = 0xCF;        // (oe)
  210.     ConvertArray[0xFB] = 0xA7;        // (germandbls)
  211.     ConvertArray[0xFC] = NullCharacter;    // (thorn)
  212.     ConvertArray[0xFD] = 0xD8;        // (ydieresis)
  213.     ConvertArray[0xFE] = NullCharacter;    // (not assigned)
  214.     ConvertArray[0xFF] = NullCharacter;    // (ascii control char?)
  215.     return self;
  216. }
  217.  
  218.  
  219.  
  220.  
  221. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  222. //    Routine:        ConvertCharacter:
  223. //    Parameters:    a character to be converted
  224. //    Returns:        the converted character
  225. //    Stores:        the character that we are returning.
  226. //    Description:
  227. //        This uses the ConvertArray set up in the initialization to convert
  228. //        a character from the NeXT character set to a Mac char.  It allows for converting
  229. //        single quotes to either Mac style (grave accent and single neuter quote) or to
  230. //        curly mac quotes (not in the lower ascii range)  It returns the converted
  231. //        character and a result code based on its succes.
  232. //    Bugs:
  233. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  234. - (Character) ConvertCharacter: (Character) theCharacter
  235. {
  236.     Character    result;
  237.     Boolean        couldconvert = YES;
  238.     [self ResetResults];
  239.     //
  240.     //    Look up our result in the conversion array.     //
  241.     result = ConvertArray[theCharacter];
  242.     //
  243.     //    If we've been asked to convert ` and ' to nice Mac curly quotes,
  244.     //    rather than ˋ and ', then see if we got a quote, and change the result
  245.     //    appropriately.
  246.     //
  247.     if (UseCurlyQuotes == YES)
  248.     {
  249.         if (theCharacter == 0x27)
  250.             result = 0xD5;        // (quoteright)
  251.         else if (theCharacter == 0x60)
  252.             result = 0xD4;        // (quoteleft)
  253.     }
  254.     //
  255.     //    Alternately, if we got a null back, and we were give (and we don't didn't
  256.     //    pass a null), indicate we could not convet properly.
  257.     //
  258.     if ((result == NullCharacter) &&  (theCharacter != NullCharacter))
  259.     {
  260.         result = theCharacter;
  261.         couldconvert = NO;
  262.     }
  263.     //
  264.     //    Store the result, and return.
  265.     //
  266.     [self    PutCharacter: result Into: FIRST_RESULT];
  267.     if (couldconvert == YES)
  268.         [self    StoreErrorCode: errOK AndText: "Character converted!"];
  269.     else
  270.         [self    StoreErrorCode: errCANTMAPTOONE AndText: "No equivalent standard Macintosh character"];
  271.     return result;
  272. }
  273.  
  274.  
  275. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  276. //    Routine:        ConvertString:WithLength:
  277. //    Parameters:    a pointer to a string of data to be converted
  278. //                the length of the data the poiner poins to.
  279. //    Returns:        a poiner to a new block of data to be converted
  280. //    Stores:        the pointer we are returning
  281. //                the length of the new data
  282. //    Description:
  283. //        This converts the text in the source data area into a new area.
  284. //        This is passed a string of characters.  This then creates a new string,
  285. //        and converts all the source characters from a Macintosh encoding to
  286. //        the destination string.  This differs from ConvertCharacter:, above, int only
  287. //        two ways:  The first is that this processes multiple characters at once.
  288. //        the second is that if it finds a character that's doens't map to a specific
  289. //        alternate character, it will replace it with a multi character string.  E.g.
  290. //        less  than or equal to is replaced with <=  And the apple symbol is just
  291. //        replaced with [apple].  The source string is not altered in any way.  The
  292. //        caller is responsible for disposing of the returned string.
  293. //    Bugs:
  294. //        we don't really check for errors anywhere (not taht there are many oportunities)...
  295. //    History
  296. //        92.12.31    djb    Added a null-character termination to the string.
  297. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  298. - (Pointer) ConvertString: (Pointer) theData WithLength: (Integer) length
  299. {
  300.     Character*    source = (Character*) theData; // getting a better typed ptr.
  301.     Integer        index;
  302.     PositiveInteger    destindex = 0;
  303.     Integer        destsize = length*1.5;
  304.     Integer        replacelength;
  305.     CString        replacement;
  306.     Character*    temp, *dest = (Character*) NewPointer(destsize);
  307.     Character    result;
  308.     [self    ResetResults];
  309.     for (index = 0; index < length; index++)
  310.     {
  311.         //
  312.         //    Look up our result in the conversion array.         //
  313.         result = ConvertArray[source[index]];
  314.         //
  315.         //    If we've been asked to convert ` and ' to nice Mac curly quotes,
  316.         //    rather than ˋ and ', then see if we got a quote, and change the result
  317.         //    appropriately.
  318.         //
  319.         if (UseCurlyQuotes == YES)
  320.         {
  321.             if (source[index] == 0x27)
  322.                 result = 0xD5;        // (quoteright)
  323.             else if (source[index] == 0x60)
  324.                 result = 0xD4;        // (quoteleft)
  325.         }
  326.         //
  327.         //    If our result is not a null (or if we passed a null), stick the result into
  328.         //    the destination space.  increment the space if necessary.
  329.         //
  330.         if ((result != NullCharacter) ||  (source[index] == NullCharacter))
  331.         {
  332.             if (destindex >= destsize)
  333.             {
  334.                 temp = NewPointer(destsize +512);
  335.                 memcpy(temp, dest, destsize);
  336.                 FreePointer(dest);
  337.                 dest = temp;
  338.                 destsize += 512;
  339.             }
  340.             dest[destindex] = result;
  341.             destindex++;
  342.         }
  343.         else
  344.         {
  345.             //
  346.             //    We evidently got a null back, telling us 'yo! I can't convert this to
  347.             //    a different single character'.  So, now we determine which it was, and
  348.             //    determine what string to use in its place.  Generally, we use the PS
  349.             //    name for the character in []'s.
  350.             //
  351.             switch (source[index])
  352.             {
  353.                 case 0x90:            // (Eth)
  354.                     replacement = "[Eth]";
  355.                     break;
  356.                 case 0x9B:            // (Yacute)
  357.                     replacement = "[Yacute]";
  358.                     break;
  359.                 case 0x9C:            // (Thorn)
  360.                     replacement = "[Thorn]";
  361.                     break;
  362.                 case 0x9E:            // (multiply)
  363.                     replacement = "[multiply]";
  364.                     break;
  365.                 case 0xB5:            // (brokenbar)
  366.                     replacement = "[brokenbar]";
  367.                     break;
  368.                 case 0xC0:            // (onesuperior)
  369.                     replacement = "[onesuperior]";
  370.                     break;
  371.                 case 0xC9:            // (twosuperior)
  372.                     replacement = "[twosuperior]";
  373.                     break;
  374.                 case 0xCC:            // (threesuperior)
  375.                     replacement = "[threesuperior]";
  376.                     break;
  377.                 case 0xD2:            // (onequarter)
  378.                     replacement = "[onequarter]";
  379.                     break;
  380.                 case 0xD3:            // (onehalf)
  381.                     replacement = "[onehalf]";
  382.                     break;
  383.                 case 0xD4:            // (threequarters)
  384.                     replacement = "[threequarters]";
  385.                     break;
  386.                 case 0xE6:            // (eth)
  387.                     replacement = "[eth]";
  388.                     break;
  389.                 case 0xE8:            // (Lslash)
  390.                     replacement = "[Lslash]";
  391.                     break;
  392.                 case 0xF7:            // (yacute)
  393.                     replacement = "[yacute]";
  394.                     break;
  395.                 case 0xF8:            // (lslash)
  396.                     replacement = "[lslash]";
  397.                     break;
  398.                 case 0xFC:            // (thorn)
  399.                     replacement = "[thorn]";
  400.                     break;
  401.                 case 0xFE:            // (not assigned)
  402.                     replacement = "[not defined]";
  403.                     break;
  404.                 case 0xFF:            // (ascii control char?)
  405.                     replacement = "[ascii control char]";
  406.                     break;                default:
  407.                     replacement = "[[THERE IS A BUG IN THE PROIGRAM (no joke)]]";
  408.                     break;
  409.             }
  410.             //
  411.             //    With a string in hand to use now, get it's length, and assure that we
  412.             //    have space to store it (if not, increment the memory block's size).
  413.             //    copy the string into the output memory space, and continue.
  414.             //
  415.             replacelength = strlen(replacement);
  416.             if ( (destindex+replacelength) >= destsize)
  417.             {
  418.                 temp = NewPointer(destsize + 512);
  419.                 memcpy(temp, dest, destsize);
  420.                 FreePointer(dest);
  421.                 dest = temp;
  422.                 destsize = destsize + 512;
  423.             }
  424.             memcpy(&dest[destindex], replacement, strlen(replacement));
  425.             destindex += replacelength;
  426.         }
  427.     }
  428.     //
  429.     //    Added, so that the block of memory returned is also null terminated.
  430.     //
  431.     if (destindex >= destsize)
  432.     {
  433.         temp = NewPointer(destsize +512);
  434.         memcpy(temp, dest, destsize);
  435.         FreePointer(dest);
  436.         dest = temp;
  437.         destsize += 512;
  438.     }
  439.     dest[destindex] = EndOfCString;
  440.     //
  441.     //    Store the result, and return.  (note that destindex always ends up pointing to
  442.     //    the next byte to be used, and thus is also a count of the total number of bytes
  443.     //    in the dest string.
  444.     //
  445.     [self    StorePointer: dest];
  446.     [self    PutPositiveInteger: destindex Into: SECOND_RESULT];
  447.     [self    StoreErrorCode: errOK AndText: "Nothing could go wrong (pathetic program)!"];
  448.     return dest;
  449. }
  450.  
  451.  
  452. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  453. //    Routine:        ConvertSingleQuotes:
  454. //    Parameters:    a boolean value
  455. //    Returns:        self
  456. //    Stores:        none
  457. //    Description:
  458. //        This simply allows the user to toggle whether they want to do convert single
  459. //        quotes to pretty curly quotes on the Mac or not.
  460. //    Bugs:
  461. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  462. - ConvertSingleQuotes:  (Boolean) useCurlyQuotes
  463. {
  464.     UseCurlyQuotes = useCurlyQuotes;
  465.     return self;
  466. }
  467. @end
  468.